﻿using HTMLTablePageScanner;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using DeepZoomPivotConstructor.PivotLib;
using System.Collections.Generic;
using t_TestingLibrary;
using System.ComponentModel.Composition;
using PaperRenderingInterfaces;
using System.IO;
using System.Linq;
using RenderEngineInterfaces;
using DeepZoomPivotConstructor.VisualLib;
using System.Drawing;
using PaperPluginUtilities;
using System.Diagnostics;
using t_PivotGeneratorTestHelpers;

namespace t_HTMLTablePageScanner
{
    
    
    /// <summary>
    ///This is a test class for WebPageScannerTest and is intended
    ///to contain all WebPageScannerTest Unit Tests
    ///</summary>
    [TestClass()]
    public class t_WebPageScanner
    {


        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion

        [TestInitialize]
        public void TestSetup()
        {
            Utilities.MyClassInit();
        }

        [TestCleanup]
        public void TestCleanup()
        {
            Utilities.MyClassDone();
        }

        /// <summary>
        ///A test for WebPageScanner Constructor
        ///</summary>
        [TestMethod]
        public void WebPageScannerConstructorTest()
        {
            WebPageScanner target = new WebPageScanner();
        }


        /// <summary>
        /// Hunt throught the metadata!
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="pmf"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        private T1[] FindMetadata<T1>(PivotImage pmf, string p)
            where T1 : PivotMetadataBase
        {
            var md = from m in pmf
                     where m.Name == p && m.GetType() == typeof(T1)
                     let masType = (T1)m
                     where masType != null
                     select masType;
            return md.ToArray();
        }

        [Export(typeof(IRenderEngine))]
        class RenderEngineDummy : IRenderEngine
        {
            public System.Threading.Tasks.Task<DeepZoomPivotConstructor.VisualLib.Visual> RenderToFuture(object what, Type[] disallowRenderPlugins = null, bool forceAsComposableUnit = false, bool requestComposableUnit = false)
            {
                throw new NotImplementedException();
            }

            public DeepZoomPivotConstructor.VisualLib.Visual Render(object what, Type[] disallowRenderPlugins = null, bool forceAsComposableUnit = false, bool requestComposableUnit = false)
            {
                Visual v = new VisualBitmapImage(1.0, 1.0, 100, Color.Black);
                if (forceAsComposableUnit)
                {
                    v.SetAsComposableUnit(null);
                }
                System.Diagnostics.Trace.WriteLine("Rendering " + what.ToString());
                return v;
            }

            private void Trace(string p)
            {
                throw new NotImplementedException();
            }
        }
        
        [TestMethod]
        public void TestExtractSimpleATLASHTML()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\ATLASMuon.htm") };
            Utilities.AddPart(laf);
            Utilities.AddPart(new RenderEngineDummy());
            Utilities.Compose(target);

            var result = target.Render("https://twiki.cern.ch/twiki/bin/view/Atlas/MuonPerformancePublicPlots");
            var results = result.ToArray();

            Assert.AreEqual("https://twiki.cern.ch/twiki/bin/view/Atlas/MuonPerformancePublicPlots", laf.UrlAskedFor, "Url request wasn't what we expected!");

            Assert.AreEqual(14, result.Count(), "Wrong number of pictures were picked up!");
            PivotImage pi = result.First();
            PivotImage pi2 = result.Skip(1).First();

            /// Note: the title is truncated to 40 characters!
            Assert.AreEqual("atlas2009-collision-vp1-141749-133538-2m", pi.Name, "Name of image is not right");
            Assert.AreEqual("run141749etc_phi", pi2.Name, "Name of second image not right!");

            CheckForGoodText(pi.Description, "first image description");
            CheckForGoodText(pi2.Description, "second image description ");

            Assert.IsTrue(pi.Count() > 0, "Expected some meta data with the image");
            Assert.IsTrue(pi2.Count() > 0, "Expect some meta data for the second image!");

            Assert.AreEqual(1, FindMetadata<PivotMetadataURL>(pi, "Graphics Files").Count(), "Expecting only a single link for the first image");
            Assert.AreEqual(2, FindMetadata<PivotMetadataURL>(pi2, "Graphics Files").Count(), "Expecting 2 links for the second images");

            Assert.AreEqual(1, FindMetadata<PivotMetadataString>(pi, "Caption").Count(), "There should be one caption!");

            Assert.AreEqual(1, FindMetadata<PivotMetadataURL>(pi, "More Information").Count(), "Expecting 1 links to more information");

            Assert.AreEqual(1, FindMetadata<PivotMetadataString>(pi, "Note Title").Count(), "Expecting a note title!");

            Assert.AreEqual(1, FindMetadata<PivotMetadataDateTime>(pi, "Date").Count(), "There should been a date!");

            Assert.IsNotNull(pi.Image, "Image of first image should not be null!");
            Assert.IsTrue(pi.Image.IsCompositionUnit, "And the image should be a composable unit!");

            ImageChecks.CheckNameAndDescription(results);
            ImageChecks.CheckForStandardMetadata(results);
        }

        [TestMethod]
        public void TestUsingRelativeURLsInWebPageImages()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\ATLASTrigger.html") };
            Utilities.AddPart(laf);
            var red = new RenderEngineDummy();
            Utilities.AddPart(red);
            Utilities.Compose(target);

            var result = target.Render("https://twiki.cern.ch/twiki/bin/view/Atlas/TriggerPublicResults");
            Assert.IsNotNull(result, "expected a good return of images!");
            var results = result.ToArray();
            Assert.AreEqual(72, results.Count(), "Expected proper number of plots from trigger page!");
            ImageChecks.CheckNameAndDescription(results);
            ImageChecks.CheckForStandardMetadata(results);
        }

        [TestMethod]
        public void TestForBadHTMLInCaptions()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\ATLASTriggerTwo.htm") };
            Utilities.AddPart(laf);
            var red = new RenderEngineDummy();
            Utilities.AddPart(red);
            Utilities.Compose(target);

            var result = target.Render("https://twiki.cern.ch/twiki/bin/view/Atlas/TriggerPublicResults");
            var results = result.ToArray();

            var allCaptions = from img in results
                              from fac in img
                              where fac.Name == "Caption"
                              select ((PivotMetadataString)fac).Value;
            foreach (var caption in allCaptions)
            {
                Trace.WriteLine("Caption: " + caption);
            }

            Assert.AreEqual(0, allCaptions.Where(s => s.Contains("&lt;")).Count(), "Should have zero of the lt's in the caption strings");
            Assert.AreEqual(0, allCaptions.Where(s => s.Contains("      ")).Count(), "Should not have lots of spaces");

            /// There is one name that is ok, but is actually bad in our tests in here.
            ImageChecks.CheckNameAndDescription(results);
            ImageChecks.CheckForStandardMetadata(results);
        }

        [TestMethod]
        public void TestForBadInitialParsing()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\ATLASTriggerTwo.htm") };
            Utilities.AddPart(laf);
            var red = new RenderEngineDummy();
            Utilities.AddPart(red);
            Utilities.Compose(target);

            var result = target.Render("https://twiki.cern.ch/twiki/bin/view/Atlas/TriggerPublicResults");
            var results = result.ToArray();

            var allDescriptions = from img in results
                              select img.Description;
            foreach (var caption in allDescriptions)
            {
                Trace.WriteLine("Description: " + caption);
            }

            Assert.AreEqual(0, allDescriptions.Where(s => s.StartsWith("to offline matching criteria")).Count(), "Should have zero funny description starts");
            ImageChecks.CheckNameAndDescription(results);
            ImageChecks.CheckForStandardMetadata(results);
        }

        [TestMethod]
        public void TestPixelResultsForNoEPSInName()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\pixel.html") };
            Utilities.AddPart(laf);
            var red = new RenderEngineDummy();
            Utilities.AddPart(red);
            Utilities.Compose(target);

            var result = target.Render("https://twiki.cern.ch/twiki/bin/view/Atlas/PixelPublicResults");
            var results = result.ToArray();
            results.Execute(p => Trace.WriteLine("Image name: " + p.Name));
            Assert.IsTrue(result.All(pi => !pi.Name.EndsWith("eps")), "Some of the image names end with a 'eps!'");
            ImageChecks.CheckNameAndDescription(results);
            ImageChecks.CheckForStandardMetadata(results);
        }

        [TestMethod]
        public void TestNullInfo2()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\ATLASID.html") };
            Utilities.AddPart(laf);
            var red = new RenderEngineDummy();
            Utilities.AddPart(red);
            Utilities.Compose(target);

            var result = target.Render("http://www-cdf.fnal.gov/physics/new/bottom/060921.blessed-double-charm-corr/");
            var results = result.ToArray();
            ImageChecks.CheckNameAndDescription(results);
        }

        private void CheckForGoodText(string theString, string message)
        {
            Assert.IsFalse(theString.Contains('\n'), message + " contains a carriage retunr!");
            Assert.IsFalse(theString.Contains("nbsp"), message + " contains a  non-breaknig space!");
            Assert.IsFalse(theString.Contains("  "), message + " contains double spaces!");
        }

        [TestMethod]
        public void TestDateTooSoon()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\ApprovedPlotsED.html") };
            laf.DateToReturn = DateTime.Now;
            Utilities.AddPart(laf);
            var red = new RenderEngineDummy();
            Utilities.AddPart(red);
            Utilities.Compose(target);

            var result = target.Render("https://twiki.cern.ch/twiki/bin/view/Atlas/ApprovedPlotsED");
            var results = result.ToArray();
            ImageChecks.CheckForStandardMetadata(results);

            /// Make sure the date we are looking at isn't "NOW"!

            Assert.IsFalse(results.Any(img => img.Any(md => md.Name == "Date" && (DateTime.Now - (md as PivotMetadataDateTime).TheTime).TotalMinutes < 2)), "Some date/time are closer than 2 minutes to now! Ops!");
            ImageChecks.CheckNameAndDescription(results);
            ImageChecks.CheckForStandardMetadata(results);
        }

        [TestMethod]
        public void TestForEPSVersion()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\InDetTrackingPerformanceApprovedPlots.html") };
            laf.DateToReturn = DateTime.Now;
            Utilities.AddPart(laf);
            var red = new RenderEngineDummy();
            Utilities.AddPart(red);
            Utilities.Compose(target);

            var result = target.Render("https://twiki.cern.ch/twiki/bin/view/Atlas/InDetTrackingPerformanceApprovedPlots");
            var results = result.ToArray();
            ImageChecks.CheckForStandardMetadata(results);
            ImageChecks.CheckNameAndDescription(results);
        }

        [TestMethod]
        public void TestCSCNoteTwikiPage()
        {
            WebPageScanner target = new WebPageScanner();
            var laf = new LoadAFile() { theFileToLoad = new FileInfo("..\\..\\..\\t_HTMLTablePageScanner\\csc-egamma.html") };
            Utilities.AddPart(laf);
            var red = new RenderEngineDummy();
            Utilities.AddPart(red);
            Utilities.Compose(target);

            var result = target.Render("https://twiki.cern.ch/twiki/bin/view/Atlas/ElectronGammaCSCChapterFigures");
            var results = result.ToArray();

            var allDescriptions = from img in results
                                  select img.Description;
            foreach (var caption in allDescriptions)
            {
                Trace.WriteLine("Description: " + caption);
            }

            Assert.AreEqual(437, results.Length, "Unexpected # of results found!");
            ImageChecks.CheckNameAndDescription(results);
            ImageChecks.CheckForStandardMetadata(results);
        }
    }
}
